﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace 桌面相关;

public class Win32DesktopOrganizer
{
    // Win32 API声明
    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, uint dwFlags, [Out] StringBuilder pszPath);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll")]
    private static extern bool FindClose(IntPtr hFindFile);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool MoveFile(string lpExistingFileName, string lpNewFileName);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);

    private const int CSIDL_DESKTOP = 0x0000;
    private const uint SHGFP_TYPE_CURRENT = 0;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }

    public static void OrganizeDesktopWithWin32()
    {
        // 获取桌面路径
        StringBuilder desktopPath = new StringBuilder(260);
        SHGetFolderPath(IntPtr.Zero, CSIDL_DESKTOP, IntPtr.Zero, SHGFP_TYPE_CURRENT, desktopPath);

        // 创建分类目录
        string[] categories = { "Images", "Documents", "Music", "Videos" };
        foreach (string category in categories)
        {
            string dirPath = Path.Combine(desktopPath.ToString(), category);
            if (!Directory.Exists(dirPath))
            {
                CreateDirectory(dirPath, IntPtr.Zero);
            }
        }

        // 枚举桌面文件
        string searchPattern = Path.Combine(desktopPath.ToString(), "*");
        WIN32_FIND_DATA findData;
        IntPtr findHandle = FindFirstFile(searchPattern, out findData);

        if (findHandle != IntPtr.Zero)
        {
            do
            {
                if (findData.cFileName == "." || findData.cFileName == "..") continue;
                if ((findData.dwFileAttributes & 0x10) != 0) continue; // 跳过目录

                string filePath = Path.Combine(desktopPath.ToString(), findData.cFileName);
                string ext = Path.GetExtension(findData.cFileName).ToLower();
                string destDir = null;

                // 分类逻辑
                switch (ext)
                {
                    case ".jpg":
                    case ".jpeg":
                    case ".png":
                    case ".bmp":
                    case ".gif":
                        destDir = Path.Combine(desktopPath.ToString(), "Images");
                        break;
                    case ".doc":
                    case ".docx":
                    case ".pdf":
                    case ".txt":
                    case ".xls":
                    case ".xlsx":
                        destDir = Path.Combine(desktopPath.ToString(), "Documents");
                        break;
                    case ".mp3":
                    case ".wav":
                    case ".flac":
                        destDir = Path.Combine(desktopPath.ToString(), "Music");
                        break;
                    case ".mp4":
                    case ".avi":
                    case ".mkv":
                    case ".mov":
                        destDir = Path.Combine(desktopPath.ToString(), "Videos");
                        break;
                    default:
                        continue;
                }

                // 移动文件
                string destPath = Path.Combine(destDir, findData.cFileName);
                if (!MoveFile(filePath, destPath))
                {
                    int error = Marshal.GetLastWin32Error();
                    Console.WriteLine($"Failed to move {findData.cFileName}, error code: {error}");
                }
            }
            while (FindNextFile(findHandle, out findData));

            FindClose(findHandle);
        }
    }
}
